/*
 * DrawPanel.c
 *
 *  Created on: 19/02/2010
 *      Author: gustavo
 */

#include "target.h"
#include "service_scheduling.h"
#include "service_time.h"
#include "service_frt_panel.h"
#include "service_lightdot_storage.h"

#include "draw_panel.h"

static U16 panelBuffer[] = { 0, 0, 0, 0, 0, 0, 2047, 2047, 3, 3, 3, 3, 3, 0,
		1025, 2047, 2047, 1025, 0, 1022, 2047, 1539, 1539, 1571, 1855, 830, 0,
		1536, 1536, 2047, 2047, 1536, 1536, 0, 2047, 2047, 32, 32, 32, 2047,
		2047, 0, 2047, 2047, 1539, 1539, 1539, 2047, 1022, 0, 1022, 2047, 1539,
		1539, 1539, 2047, 1022, 0, 1536, 1536, 2047, 2047, 1536, 1536, 0, 0, 0,
		259, 771, 2047, 2047, 3, 3, 0, 1022, 2047, 1585, 1633, 2047, 1022, 0,
		0, 0, 1023, 2047, 1056, 1056, 1056, 2047, 1023, 0, 2047, 2047, 1584,
		1592, 1580, 2022, 963, 0, 2047, 2047, 384, 192, 384, 2047, 2047, 0, 0,
		0, 0, 0, 0 };

void draw_panel_init(void) {
}

void draw_panel_shift_columns_left() {
	U32 index, first;
	U32 bufferSize = sizeof(panelBuffer) / sizeof(panelBuffer[0]);

	first = panelBuffer[0];

	for (index = 0; index < bufferSize - 1; ++index) {
		panelBuffer[index] = panelBuffer[index + 1];
	}

	panelBuffer[bufferSize - 1] = first;
}

void draw_panel_shift_columns_right() {
	U32 index, last;
	U32 bufferSize = sizeof(panelBuffer) / sizeof(panelBuffer[0]);

	last = panelBuffer[bufferSize - 1];

	for (index = bufferSize - 1; index > 0; index--) {
		panelBuffer[index] = panelBuffer[index - 1];
	}

	panelBuffer[0] = last;
}

//TODO Remove the Fix Lenght 16 to be variable
U16 draw_panel_shiftRight(U16 byteParam) {
	U8 lastBit = byteParam & 0x01;
	byteParam >>= 1;
	byteParam |= (lastBit << (16 - 1));
	return byteParam;
}

//TODO Remove the Fix Lenght 16 to be variable
U16 draw_panel_shiftLeft(U16 byteParam) {
	U16 firstBit = byteParam & 0x8000;
	firstBit >>= 16 - 1;
	byteParam <<= 1;
	byteParam |= firstBit;
	return byteParam;
}

void draw_panel_text_bottom_up() {
	U16 i;
	U32 bufferSize = sizeof(panelBuffer) / sizeof(panelBuffer[0]);

	for (i = 1; i < bufferSize; i++) {
		panelBuffer[i] = draw_panel_shiftLeft(panelBuffer[i]);
	}
}

void draw_panel_text_top_down() {
	U16 i;
	U32 bufferSize = sizeof(panelBuffer) / sizeof(panelBuffer[0]);

	for (i = 1; i < bufferSize; i++) {
		panelBuffer[i] = draw_panel_shiftRight(panelBuffer[i]);
	}
}

#ifdef DEBUG_SHOW_PANEL
service_scheduling_TASK_FUNCTION_DECLARATION(drawPanelProcess, args)
{
	service_time_TimeTicks time;
	U32 bufferSize = sizeof(panelBuffer)/sizeof(panelBuffer[0]);
	U16 i = 0;

	service_frt_panel_sendBitmap((U16 *)panelBuffer, 11, bufferSize);

	time = service_time_getCurrentTimeTicks();

	for (i = 0; i < bufferSize; i++) {
		draw_panel_shift_columns_right();
		service_frt_panel_sendBitmap((U16 *)panelBuffer, 11, bufferSize);
		service_time_relativeDelay(&time, 25);
	}

	for (i = 0; i < bufferSize; i++) {
		draw_panel_shift_columns_left();
		service_frt_panel_sendBitmap((U16 *)panelBuffer, 11, bufferSize);
		service_time_relativeDelay(&time, 25);
	}

	for (i = 0; i < 16; i++) {
		draw_panel_text_top_down();
		service_frt_panel_sendBitmap((U16 *)panelBuffer, 11, bufferSize);
		service_time_relativeDelay(&time, 100);
	}

	for (i = 0; i < 16; i++) {
		draw_panel_text_bottom_up();
		service_frt_panel_sendBitmap((U16 *)panelBuffer, 11, bufferSize);
		service_time_relativeDelay(&time, 100);
	}
}
#else

//TODO
U16 draw_panel_GetPanelWidth() {
	return 112;
}

//TODO
U8 draw_panel_GetPanelHeight() {
	return 11;
}

//TODO
void draw_panel_Refresh_LCD() {

}

//TODO
U16 draw_panel_GetTimeout() {
	return 2000;
}

//TODO
U16 draw_panel_GetRollTime() {
	return 26;
}

void draw_panel_LoadBitmapToBuffer(service_lightdot_storage_BitmapHandle page) {
	U16 indexBuffer = 0, indexMemory = 0;
	U16 widht = service_lightdot_storage_getBitmapSize(page);
	widht = (widht + 1) / 2;

	for (indexBuffer = 0, indexMemory = 0; indexBuffer < widht; indexBuffer++, indexMemory
			+= 2) {
		panelBuffer[indexBuffer] = service_lightdot_storage_readBitmapCollumn(
				page, indexBuffer);//(U16)(flashMemory[page][indexMemory] << 8) + (flashMemory[page][indexMemory + 1]);
	}
}

void draw_panel_ClearBitmapBuffer(service_lightdot_storage_BitmapHandle page) {
	U16 indexBuffer = 0, indexMemory = 0;
	U16 widht = service_lightdot_storage_getBitmapSize(page);
	widht = (widht + 1) / 2;

	for (indexBuffer = 0, indexMemory = 0; indexBuffer < widht; indexBuffer++, indexMemory
			+= 2) {
		panelBuffer[indexBuffer] = 0x0000;
	}
}

void draw_panel_ShiftLeftUpdateColumn(U16 width, U8 height, U16 column) {

	panelBuffer[width - 1] = column;
	service_frt_panel_sendBitmap((U16 *) panelBuffer, height, width);

	draw_panel_shift_columns_left();
}

//TODO
void draw_panel_ShowBitmapPagedRoll(service_lightdot_storage_BitmapHandle page) {
	service_time_TimeTicks time;
	U16 numberColumnsPanel;

	BOOL hasMorePages = TRUE;
	U8 height = draw_panel_GetPanelHeight();

	numberColumnsPanel = draw_panel_GetPanelWidth();

	//TODO Verify if the LCD refresh will be another process
	draw_panel_Refresh_LCD();

	while (hasMorePages) {
		U16 timeout, roolTime;
		U16 i;
		U16 widht = service_lightdot_storage_getBitmapSize(page);

		draw_panel_ClearBitmapBuffer(page);

		timeout = draw_panel_GetTimeout();
		roolTime = draw_panel_GetRollTime();

		for (i = 0; i < ((widht + 1) / 2); i++) {
			U16 column = service_lightdot_storage_readBitmapCollumn(page, i);
			draw_panel_ShiftLeftUpdateColumn(numberColumnsPanel, height, column);
			time = service_time_getCurrentTimeTicks();
			service_time_relativeDelay(&time, roolTime);
		}

		time = service_time_getCurrentTimeTicks();
		service_time_relativeDelay(&time, timeout);

		hasMorePages = !service_lightdot_storage_isLastBitmap(page);
		page = service_lightdot_storage_getNextBitmap(page);
	}
}

//TODO
void draw_panel_ShowBitmapSimpleRoll(service_lightdot_storage_BitmapHandle page) {
	service_time_TimeTicks time;
	U16 numberColumnsPanel;

	BOOL hasMorePages = TRUE;

	U8 height = draw_panel_GetPanelHeight();

	//TODO Verify if the LCD refresh will be another process
	draw_panel_Refresh_LCD();

	draw_panel_ClearBitmapBuffer(page);

	numberColumnsPanel = draw_panel_GetPanelWidth();

	while (hasMorePages) {
		U16 timeout, roolTime;
		U16 i;
		U16 widht = service_lightdot_storage_getBitmapSize(page);

		timeout = draw_panel_GetTimeout();
		roolTime = draw_panel_GetRollTime();

		for (i = 0; i < ((widht + 1) / 2); i++) {
			U16 column = service_lightdot_storage_readBitmapCollumn(page, i);
			draw_panel_ShiftLeftUpdateColumn(numberColumnsPanel, height, column);
			time = service_time_getCurrentTimeTicks();
			service_time_relativeDelay(&time, roolTime);
		}

		hasMorePages = !service_lightdot_storage_isLastBitmap(page);

		if (!hasMorePages) {
			time = service_time_getCurrentTimeTicks();
			service_time_relativeDelay(&time, timeout);
		}

		page = service_lightdot_storage_getNextBitmap(page);
	}
}

//TODO
void draw_panel_ShowBitmapFixedMode(service_lightdot_storage_BitmapHandle page) {
	service_time_TimeTicks time;
	BOOL hasMorePages = TRUE;

	U8 height = draw_panel_GetPanelHeight();

	//TODO Verify if the LCD refresh will be another process
	draw_panel_Refresh_LCD();

	while (hasMorePages) {
		U16 timeout;

		U16 widht = service_lightdot_storage_getBitmapSize(page);

		time = service_time_getCurrentTimeTicks();
		draw_panel_LoadBitmapToBuffer(page);
		widht = (widht + 1)/2;
		service_frt_panel_sendBitmap((U16 *)panelBuffer, height, widht);

		timeout = draw_panel_GetTimeout();
		service_time_relativeDelay(&time, timeout);

		hasMorePages = !service_lightdot_storage_isLastBitmap(page);
		page = service_lightdot_storage_getNextBitmap(page);
	}
}

void draw_panel_ShowRolagemCircular(service_lightdot_storage_BitmapHandle page) {
	service_time_TimeTicks time;
	U16 numberColumnsPanel;

	BOOL hasMorePages = TRUE;
	U8 height = draw_panel_GetPanelHeight();

	//TODO Verify if the LCD refresh will be another process
	draw_panel_Refresh_LCD();

	draw_panel_ClearBitmapBuffer(page);

	numberColumnsPanel = draw_panel_GetPanelWidth();

	while (hasMorePages) {
		U16 roolTime;
		U16 i;
		U16 widht = service_lightdot_storage_getBitmapSize(page);

		roolTime = draw_panel_GetRollTime();

		for (i = 0; i < ((widht + 1) / 2); i++) {
			U16 column = service_lightdot_storage_readBitmapCollumn(page, i);
			draw_panel_ShiftLeftUpdateColumn(widht, height, column);
			time = service_time_getCurrentTimeTicks();
			service_time_relativeDelay(&time, roolTime);
		}

		hasMorePages = !service_lightdot_storage_isLastBitmap(page);

		if (!hasMorePages) {
			for (i = 0; i < numberColumnsPanel; i++) {
				draw_panel_ShiftLeftUpdateColumn(widht, height, 0);
				time = service_time_getCurrentTimeTicks();
				service_time_relativeDelay(&time, roolTime);
			}
		}

		page = service_lightdot_storage_getNextBitmap(page);
	}
}

void draw_panel_showBitmap(service_lightdot_storage_BitmapHandle panelPage) {
	service_lightdot_storage_BitmapShowMode showMode =
			service_lightdot_storage_getBitmapShowMode(panelPage);
	switch (showMode) {
	case service_lightdot_storage_SHOW_FIXED_MODE:
		draw_panel_ShowBitmapFixedMode(panelPage);
		break;
	case service_lightdot_storage_SHOW_SIMPLE_ROLL:
		draw_panel_ShowBitmapSimpleRoll(panelPage);
		break;
	case service_lightdot_storage_SHOW_PAGED_ROLL:
		draw_panel_ShowBitmapPagedRoll(panelPage);
		break;
	case service_lightdot_storage_SHOW_ROLAGEM_CIRCULAR:
		draw_panel_ShowRolagemCircular(panelPage);
	default:
		break;
	}
}

service_scheduling_TASK_FUNCTION_DECLARATION(drawPanelProcess, args) {
	U16 routeIndex;

	service_lightdot_storage_BitmapHandle bitmapHandler;
	service_lightdot_storage_PanelService panelService;
	service_lightdot_storage_RouteHandle routeHandler;

	panelService = service_lightdot_storage_getPanelService();
	routeIndex = service_lightdot_storage_getCurrentRouteIndex();
	routeHandler = service_lightdot_storage_getRoute(routeIndex);

	switch (panelService) {
	case ROUTE__ONLY:
		bitmapHandler = service_lightdot_storage_getRouteGoingBitmap(
				routeHandler);
		draw_panel_showBitmap(bitmapHandler);
		break;
	case EXCHANGE_W_MESSAGE:
		bitmapHandler = service_lightdot_storage_getRouteGoingBitmap(
				routeHandler);
		draw_panel_showBitmap(routeHandler);

		//TODO bitmapHandler = service_lightdot_storage_getRouteGoingBitmap(routeHandler);
		//TODO MESSAGE draw_panel_showBitmap(routeHandler);
	default:
		break;
	}
}

#endif
